<!DOCTYPE html>
<html lang="en" dir="auto">

<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="index, follow">
<title>Hierarchical Gaussian Splatting | WangJV Blog</title>
<meta name="keywords" content="3D Splatting, Gaussian Splatting, Hierarchical Rendering, 体渲染, 计算机图形学">
<meta name="description" content="1. Abstract &amp; Introduction
3D Gaussian Splatting 面临着一个几乎看起来无法规避的问题，就是我们需要给每个高斯函数分配一定的存储空间，并在训练时对其优化；并且在训练和渲染时需要同时将所有的高斯函数加载到设备的现存中，这导致训练和渲染在计算上是十分昂贵的。这导致我们总是要在渲染、重建质量和速度之间作出权衡，甚至很多时候是没办法训练的。这制约了 Splatting 在大场景的工作（例如城市级）上的应用。
那么一个很显然的想法，就是在较远时提供一个较低的分辨率，实现一个分层级的渲染和训练，并且只加载视角可见的部分。那么需要的方法有两点：

引入结构层次（Hierarchy），使用一种高效细节级别解决方案（Level of Detial）。
引入分置策略（divide-and-conquer），让我们可以在独立的训练和渲染每一个小块。

同时，通过不同层级的结构（Guassian Function）可以用来优化中间层的高斯函数。这篇文章所提出的策略可以实时的渲染非常大的场景，覆盖长达几公里的轨迹，持续长达一小时。

2. 概述和背景
2.1. 背景
3DGS 提供了一种基于体积基元的空间场景表达方法，每个体积基元含有如下特征：

位置（或者说均值$\mu$）
协方差矩阵$\Sigma$
透明度（$o$）
球谐系数（$SH$）用于表达与视角相关的颜色，或者直接使用颜色

三维基元可以投影到二维屏幕空间上，并且通过 $\alpha\text{-blander}$ 来实现光栅化。 $\alpha\text{-blander}$ 的权重为：

$$
\begin{aligned}
\alpha &= \text{oG}\\
G(x,y) &= \exp 
\left\{
-\frac 12 ([x,y]^T-\mu&#39;)^T\Sigma&#39;^{-1}([x,y]^T-\mu&#39;)
\right\}
\end{aligned}
$$
其中 $\mu&#39;$ 是三维空间基元投影到二维相机平面上基元的均值，$\Sigma&#39;$ 投影的二维基元的协方差。
3. 3DGaussian 的结构化 (hierarchy) 的细节层次 (LOD)
在处理大型场景以允许有效渲染大量内容时，细节级别 (LOD) 解决方案至关重要；因此，我们的目标是创建一个层次结构，表示原始 3DGS 优化生成的原语。遵循图形中的传统LOD方法，我们需要

找到候选3DGS基元，并定义如何将它们合并到中间节点
提供一种有效的方法来确定层次结构中的切割，从而在质量和速度之间提供良好的折衷
层次结构级别之间的平滑过渡策略

3.1. 生成不同分辨率的高斯球
我们为每个块创建一个具有内部节点和叶节点的基于树的层次结构。每个节点都与一个 3D 高斯相关联，该高斯要么是来自原始优化的叶节点，要么是合并的内部节点。我们对中间节点的要求是它们应该：

保持与叶节点相同的快速光栅化例程
尽可能准确地表示子节点的外观。因此，我们需要定义具有 3DGS 原语所有属性的 3D 高斯的中间节点。例如保持它原本所有的特征：均值$\mu$、协方差$\Sigma$、透明度 $o$ 等等。

对于均值和协方差，有很多文献详尽的描述了这个混合过程。可以通过如下公式混合 $N$ 个在第 $l$ 级的均值为 $\mu_i^l$，协方差为 $\Sigma_i^l$ 高斯函数。我们可以通过评估这 $N$ 个高斯函数和待估计的高斯函数之间的 3D Kullback-Leibler divergence。3DKL 散度描述了两个高斯函数之间的相关性。那么显然的，假设$f = \sum_{i=1}^{N}\mathcal \alpha_i N(\mu_i, \Sigma_i)$，g为我们所需要新的高斯函数，应该有：
">
<meta name="author" content="WangJV">
<link rel="canonical" href="https://wangjv0812.github.io/WangJV-Blog-Pages/2024/07/hierarchical-gaussian-splatting/">
<link crossorigin="anonymous" href="https://wangjv0812.github.io/WangJV-Blog-Pages/assets/css/stylesheet.8fe10233a706bc87f2e08b3cf97b8bd4c0a80f10675a143675d59212121037c0.css" integrity="sha256-j&#43;ECM6cGvIfy4Is8&#43;XuL1MCoDxBnWhQ2ddWSEhIQN8A=" rel="preload stylesheet" as="style">
<link rel="icon" href="https://wangjv0812.github.io/WangJV-Blog-Pages/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="https://wangjv0812.github.io/WangJV-Blog-Pages/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="https://wangjv0812.github.io/WangJV-Blog-Pages/favicon-32x32.png">
<link rel="apple-touch-icon" href="https://wangjv0812.github.io/WangJV-Blog-Pages/apple-touch-icon.png">
<link rel="mask-icon" href="https://wangjv0812.github.io/WangJV-Blog-Pages/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="en" href="https://wangjv0812.github.io/WangJV-Blog-Pages/2024/07/hierarchical-gaussian-splatting/">
<noscript>
    <style>
        #theme-toggle,
        .top-link {
            display: none;
        }

    </style>
    <style>
        @media (prefers-color-scheme: dark) {
            :root {
                --theme: rgb(29, 30, 32);
                --entry: rgb(46, 46, 51);
                --primary: rgb(218, 218, 219);
                --secondary: rgb(155, 156, 157);
                --tertiary: rgb(65, 66, 68);
                --content: rgb(196, 196, 197);
                --code-block-bg: rgb(46, 46, 51);
                --code-bg: rgb(55, 56, 62);
                --border: rgb(51, 51, 51);
            }

            .list {
                background: var(--theme);
            }

            .list:not(.dark)::-webkit-scrollbar-track {
                background: 0 0;
            }

            .list:not(.dark)::-webkit-scrollbar-thumb {
                border-color: var(--theme);
            }
        }

    </style>
</noscript><script>
  MathJax = {
    tex: {
      displayMath: [['\\[', '\\]'], ['$$', '$$']],
      inlineMath: [['\\(', '\\)'], ['$', '$']],
      processEscapes: true,
      processEnvironments: true,
      tags: 'ams'
    },
    chtml: {
      scale: 1,                     
      minScale: 0.5,               
      matchFontHeight: false,       
      displayAlign: 'center',       
      displayIndent: '0',           
      mtextInheritFont: false,      
      merrorInheritFont: true,      
      mathmlSpacing: false,         
      skipHtmlTags: ['script','noscript','style','textarea','pre','code','a'],
      ignoreHtmlClass: 'tex2jax_ignore',
      processHtmlClass: 'tex2jax_process'
    },
    svg: {
      scale: 1,                     
      minScale: 0.5,               
      mtextInheritFont: false,      
      merrorInheritFont: true,
      mathmlSpacing: false,
      skipHtmlTags: ['script','noscript','style','textarea','pre','code','a'],
      ignoreHtmlClass: 'tex2jax_ignore',
      processHtmlClass: 'tex2jax_process'
    },
    options: {
      enableMenu: true,             
      menuOptions: {
        settings: {
          zoom: 'Click'             
        }
      }
    },
    loader: {
      load: ['ui/safe', 'a11y/assistive-mml']
    },
    startup: {
      ready() {
        MathJax.startup.defaultReady();
        
        const observer = new ResizeObserver(entries => {
          MathJax.typesetPromise();
        });
        observer.observe(document.body);
      }
    }
  };
  
  
  if (window.innerWidth <= 768) {
    MathJax.chtml = MathJax.chtml || {};
    MathJax.chtml.scale = 0.9;  
  }
</script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>


<style>
   
  .MathJax {
    outline: 0;
  }
  
   
  @media (max-width: 768px) {
    .MathJax {
      font-size: 90% !important;
    }
    
     
    .MathJax_Display {
      overflow-x: auto;
      overflow-y: hidden;
      padding: 0 !important;
      margin: 1em 0 !important;
    }
    
     
    .MathJax_CHTML {
      line-height: 1.2 !important;
    }
  }
  
   
  mjx-container[jax="CHTML"][display="true"] {
    overflow-x: auto;
    overflow-y: hidden;
    padding: 1px 0;
  }
</style><meta property="og:url" content="https://wangjv0812.github.io/WangJV-Blog-Pages/2024/07/hierarchical-gaussian-splatting/">
  <meta property="og:site_name" content="WangJV Blog">
  <meta property="og:title" content="Hierarchical Gaussian Splatting">
  <meta property="og:description" content="1. Abstract &amp; Introduction 3D Gaussian Splatting 面临着一个几乎看起来无法规避的问题，就是我们需要给每个高斯函数分配一定的存储空间，并在训练时对其优化；并且在训练和渲染时需要同时将所有的高斯函数加载到设备的现存中，这导致训练和渲染在计算上是十分昂贵的。这导致我们总是要在渲染、重建质量和速度之间作出权衡，甚至很多时候是没办法训练的。这制约了 Splatting 在大场景的工作（例如城市级）上的应用。
那么一个很显然的想法，就是在较远时提供一个较低的分辨率，实现一个分层级的渲染和训练，并且只加载视角可见的部分。那么需要的方法有两点：
引入结构层次（Hierarchy），使用一种高效细节级别解决方案（Level of Detial）。 引入分置策略（divide-and-conquer），让我们可以在独立的训练和渲染每一个小块。 同时，通过不同层级的结构（Guassian Function）可以用来优化中间层的高斯函数。这篇文章所提出的策略可以实时的渲染非常大的场景，覆盖长达几公里的轨迹，持续长达一小时。
2. 概述和背景 2.1. 背景 3DGS 提供了一种基于体积基元的空间场景表达方法，每个体积基元含有如下特征：
位置（或者说均值$\mu$） 协方差矩阵$\Sigma$ 透明度（$o$） 球谐系数（$SH$）用于表达与视角相关的颜色，或者直接使用颜色 三维基元可以投影到二维屏幕空间上，并且通过 $\alpha\text{-blander}$ 来实现光栅化。 $\alpha\text{-blander}$ 的权重为： $$ \begin{aligned} \alpha &amp;= \text{oG}\\ G(x,y) &amp;= \exp \left\{ -\frac 12 ([x,y]^T-\mu&#39;)^T\Sigma&#39;^{-1}([x,y]^T-\mu&#39;) \right\} \end{aligned} $$ 其中 $\mu&#39;$ 是三维空间基元投影到二维相机平面上基元的均值，$\Sigma&#39;$ 投影的二维基元的协方差。
3. 3DGaussian 的结构化 (hierarchy) 的细节层次 (LOD) 在处理大型场景以允许有效渲染大量内容时，细节级别 (LOD) 解决方案至关重要；因此，我们的目标是创建一个层次结构，表示原始 3DGS 优化生成的原语。遵循图形中的传统LOD方法，我们需要
找到候选3DGS基元，并定义如何将它们合并到中间节点 提供一种有效的方法来确定层次结构中的切割，从而在质量和速度之间提供良好的折衷 层次结构级别之间的平滑过渡策略 3.1. 生成不同分辨率的高斯球 我们为每个块创建一个具有内部节点和叶节点的基于树的层次结构。每个节点都与一个 3D 高斯相关联，该高斯要么是来自原始优化的叶节点，要么是合并的内部节点。我们对中间节点的要求是它们应该：
保持与叶节点相同的快速光栅化例程 尽可能准确地表示子节点的外观。因此，我们需要定义具有 3DGS 原语所有属性的 3D 高斯的中间节点。例如保持它原本所有的特征：均值$\mu$、协方差$\Sigma$、透明度 $o$ 等等。 对于均值和协方差，有很多文献详尽的描述了这个混合过程。可以通过如下公式混合 $N$ 个在第 $l$ 级的均值为 $\mu_i^l$，协方差为 $\Sigma_i^l$ 高斯函数。我们可以通过评估这 $N$ 个高斯函数和待估计的高斯函数之间的 3D Kullback-Leibler divergence。3DKL 散度描述了两个高斯函数之间的相关性。那么显然的，假设$f = \sum_{i=1}^{N}\mathcal \alpha_i N(\mu_i, \Sigma_i)$，g为我们所需要新的高斯函数，应该有： ">
  <meta property="og:locale" content="en-us">
  <meta property="og:type" content="article">
    <meta property="article:section" content="posts">
    <meta property="article:published_time" content="2024-07-08T16:40:25+08:00">
    <meta property="article:modified_time" content="2024-07-08T16:40:25+08:00">
    <meta property="article:tag" content="3D Splatting">
    <meta property="article:tag" content="Gaussian Splatting">
    <meta property="article:tag" content="Hierarchical Rendering">
    <meta property="article:tag" content="体渲染">
    <meta property="article:tag" content="计算机图形学">
      <meta property="og:image" content="https://wangjv0812.github.io/WangJV-Blog-Pages/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://wangjv0812.github.io/WangJV-Blog-Pages/">
<meta name="twitter:title" content="Hierarchical Gaussian Splatting">
<meta name="twitter:description" content="1. Abstract &amp; Introduction
3D Gaussian Splatting 面临着一个几乎看起来无法规避的问题，就是我们需要给每个高斯函数分配一定的存储空间，并在训练时对其优化；并且在训练和渲染时需要同时将所有的高斯函数加载到设备的现存中，这导致训练和渲染在计算上是十分昂贵的。这导致我们总是要在渲染、重建质量和速度之间作出权衡，甚至很多时候是没办法训练的。这制约了 Splatting 在大场景的工作（例如城市级）上的应用。
那么一个很显然的想法，就是在较远时提供一个较低的分辨率，实现一个分层级的渲染和训练，并且只加载视角可见的部分。那么需要的方法有两点：

引入结构层次（Hierarchy），使用一种高效细节级别解决方案（Level of Detial）。
引入分置策略（divide-and-conquer），让我们可以在独立的训练和渲染每一个小块。

同时，通过不同层级的结构（Guassian Function）可以用来优化中间层的高斯函数。这篇文章所提出的策略可以实时的渲染非常大的场景，覆盖长达几公里的轨迹，持续长达一小时。

2. 概述和背景
2.1. 背景
3DGS 提供了一种基于体积基元的空间场景表达方法，每个体积基元含有如下特征：

位置（或者说均值$\mu$）
协方差矩阵$\Sigma$
透明度（$o$）
球谐系数（$SH$）用于表达与视角相关的颜色，或者直接使用颜色

三维基元可以投影到二维屏幕空间上，并且通过 $\alpha\text{-blander}$ 来实现光栅化。 $\alpha\text{-blander}$ 的权重为：

$$
\begin{aligned}
\alpha &= \text{oG}\\
G(x,y) &= \exp 
\left\{
-\frac 12 ([x,y]^T-\mu&#39;)^T\Sigma&#39;^{-1}([x,y]^T-\mu&#39;)
\right\}
\end{aligned}
$$
其中 $\mu&#39;$ 是三维空间基元投影到二维相机平面上基元的均值，$\Sigma&#39;$ 投影的二维基元的协方差。
3. 3DGaussian 的结构化 (hierarchy) 的细节层次 (LOD)
在处理大型场景以允许有效渲染大量内容时，细节级别 (LOD) 解决方案至关重要；因此，我们的目标是创建一个层次结构，表示原始 3DGS 优化生成的原语。遵循图形中的传统LOD方法，我们需要

找到候选3DGS基元，并定义如何将它们合并到中间节点
提供一种有效的方法来确定层次结构中的切割，从而在质量和速度之间提供良好的折衷
层次结构级别之间的平滑过渡策略

3.1. 生成不同分辨率的高斯球
我们为每个块创建一个具有内部节点和叶节点的基于树的层次结构。每个节点都与一个 3D 高斯相关联，该高斯要么是来自原始优化的叶节点，要么是合并的内部节点。我们对中间节点的要求是它们应该：

保持与叶节点相同的快速光栅化例程
尽可能准确地表示子节点的外观。因此，我们需要定义具有 3DGS 原语所有属性的 3D 高斯的中间节点。例如保持它原本所有的特征：均值$\mu$、协方差$\Sigma$、透明度 $o$ 等等。

对于均值和协方差，有很多文献详尽的描述了这个混合过程。可以通过如下公式混合 $N$ 个在第 $l$ 级的均值为 $\mu_i^l$，协方差为 $\Sigma_i^l$ 高斯函数。我们可以通过评估这 $N$ 个高斯函数和待估计的高斯函数之间的 3D Kullback-Leibler divergence。3DKL 散度描述了两个高斯函数之间的相关性。那么显然的，假设$f = \sum_{i=1}^{N}\mathcal \alpha_i N(\mu_i, \Sigma_i)$，g为我们所需要新的高斯函数，应该有：
">


<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position":  1 ,
      "name": "Posts",
      "item": "https://wangjv0812.github.io/WangJV-Blog-Pages/posts/"
    }, 
    {
      "@type": "ListItem",
      "position":  2 ,
      "name": "Hierarchical Gaussian Splatting",
      "item": "https://wangjv0812.github.io/WangJV-Blog-Pages/2024/07/hierarchical-gaussian-splatting/"
    }
  ]
}
</script>
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "Hierarchical Gaussian Splatting",
  "name": "Hierarchical Gaussian Splatting",
  "description": "1. Abstract \u0026amp; Introduction 3D Gaussian Splatting 面临着一个几乎看起来无法规避的问题，就是我们需要给每个高斯函数分配一定的存储空间，并在训练时对其优化；并且在训练和渲染时需要同时将所有的高斯函数加载到设备的现存中，这导致训练和渲染在计算上是十分昂贵的。这导致我们总是要在渲染、重建质量和速度之间作出权衡，甚至很多时候是没办法训练的。这制约了 Splatting 在大场景的工作（例如城市级）上的应用。\n那么一个很显然的想法，就是在较远时提供一个较低的分辨率，实现一个分层级的渲染和训练，并且只加载视角可见的部分。那么需要的方法有两点：\n引入结构层次（Hierarchy），使用一种高效细节级别解决方案（Level of Detial）。 引入分置策略（divide-and-conquer），让我们可以在独立的训练和渲染每一个小块。 同时，通过不同层级的结构（Guassian Function）可以用来优化中间层的高斯函数。这篇文章所提出的策略可以实时的渲染非常大的场景，覆盖长达几公里的轨迹，持续长达一小时。\n2. 概述和背景 2.1. 背景 3DGS 提供了一种基于体积基元的空间场景表达方法，每个体积基元含有如下特征：\n位置（或者说均值$\\mu$） 协方差矩阵$\\Sigma$ 透明度（$o$） 球谐系数（$SH$）用于表达与视角相关的颜色，或者直接使用颜色 三维基元可以投影到二维屏幕空间上，并且通过 $\\alpha\\text{-blander}$ 来实现光栅化。 $\\alpha\\text{-blander}$ 的权重为： $$ \\begin{aligned} \\alpha \u0026= \\text{oG}\\\\ G(x,y) \u0026= \\exp \\left\\{ -\\frac 12 ([x,y]^T-\\mu')^T\\Sigma'^{-1}([x,y]^T-\\mu') \\right\\} \\end{aligned} $$ 其中 $\\mu'$ 是三维空间基元投影到二维相机平面上基元的均值，$\\Sigma'$ 投影的二维基元的协方差。\n3. 3DGaussian 的结构化 (hierarchy) 的细节层次 (LOD) 在处理大型场景以允许有效渲染大量内容时，细节级别 (LOD) 解决方案至关重要；因此，我们的目标是创建一个层次结构，表示原始 3DGS 优化生成的原语。遵循图形中的传统LOD方法，我们需要\n找到候选3DGS基元，并定义如何将它们合并到中间节点 提供一种有效的方法来确定层次结构中的切割，从而在质量和速度之间提供良好的折衷 层次结构级别之间的平滑过渡策略 3.1. 生成不同分辨率的高斯球 我们为每个块创建一个具有内部节点和叶节点的基于树的层次结构。每个节点都与一个 3D 高斯相关联，该高斯要么是来自原始优化的叶节点，要么是合并的内部节点。我们对中间节点的要求是它们应该：\n保持与叶节点相同的快速光栅化例程 尽可能准确地表示子节点的外观。因此，我们需要定义具有 3DGS 原语所有属性的 3D 高斯的中间节点。例如保持它原本所有的特征：均值$\\mu$、协方差$\\Sigma$、透明度 $o$ 等等。 对于均值和协方差，有很多文献详尽的描述了这个混合过程。可以通过如下公式混合 $N$ 个在第 $l$ 级的均值为 $\\mu_i^l$，协方差为 $\\Sigma_i^l$ 高斯函数。我们可以通过评估这 $N$ 个高斯函数和待估计的高斯函数之间的 3D Kullback-Leibler divergence。3DKL 散度描述了两个高斯函数之间的相关性。那么显然的，假设$f = \\sum_{i=1}^{N}\\mathcal \\alpha_i N(\\mu_i, \\Sigma_i)$，g为我们所需要新的高斯函数，应该有： ",
  "keywords": [
    "3D Splatting", "Gaussian Splatting", "Hierarchical Rendering", "体渲染", "计算机图形学"
  ],
  "articleBody": "1. Abstract \u0026 Introduction 3D Gaussian Splatting 面临着一个几乎看起来无法规避的问题，就是我们需要给每个高斯函数分配一定的存储空间，并在训练时对其优化；并且在训练和渲染时需要同时将所有的高斯函数加载到设备的现存中，这导致训练和渲染在计算上是十分昂贵的。这导致我们总是要在渲染、重建质量和速度之间作出权衡，甚至很多时候是没办法训练的。这制约了 Splatting 在大场景的工作（例如城市级）上的应用。\n那么一个很显然的想法，就是在较远时提供一个较低的分辨率，实现一个分层级的渲染和训练，并且只加载视角可见的部分。那么需要的方法有两点：\n引入结构层次（Hierarchy），使用一种高效细节级别解决方案（Level of Detial）。 引入分置策略（divide-and-conquer），让我们可以在独立的训练和渲染每一个小块。 同时，通过不同层级的结构（Guassian Function）可以用来优化中间层的高斯函数。这篇文章所提出的策略可以实时的渲染非常大的场景，覆盖长达几公里的轨迹，持续长达一小时。\n2. 概述和背景 2.1. 背景 3DGS 提供了一种基于体积基元的空间场景表达方法，每个体积基元含有如下特征：\n位置（或者说均值$\\mu$） 协方差矩阵$\\Sigma$ 透明度（$o$） 球谐系数（$SH$）用于表达与视角相关的颜色，或者直接使用颜色 三维基元可以投影到二维屏幕空间上，并且通过 $\\alpha\\text{-blander}$ 来实现光栅化。 $\\alpha\\text{-blander}$ 的权重为： $$ \\begin{aligned} \\alpha \u0026= \\text{oG}\\\\ G(x,y) \u0026= \\exp \\left\\{ -\\frac 12 ([x,y]^T-\\mu')^T\\Sigma'^{-1}([x,y]^T-\\mu') \\right\\} \\end{aligned} $$ 其中 $\\mu'$ 是三维空间基元投影到二维相机平面上基元的均值，$\\Sigma'$ 投影的二维基元的协方差。\n3. 3DGaussian 的结构化 (hierarchy) 的细节层次 (LOD) 在处理大型场景以允许有效渲染大量内容时，细节级别 (LOD) 解决方案至关重要；因此，我们的目标是创建一个层次结构，表示原始 3DGS 优化生成的原语。遵循图形中的传统LOD方法，我们需要\n找到候选3DGS基元，并定义如何将它们合并到中间节点 提供一种有效的方法来确定层次结构中的切割，从而在质量和速度之间提供良好的折衷 层次结构级别之间的平滑过渡策略 3.1. 生成不同分辨率的高斯球 我们为每个块创建一个具有内部节点和叶节点的基于树的层次结构。每个节点都与一个 3D 高斯相关联，该高斯要么是来自原始优化的叶节点，要么是合并的内部节点。我们对中间节点的要求是它们应该：\n保持与叶节点相同的快速光栅化例程 尽可能准确地表示子节点的外观。因此，我们需要定义具有 3DGS 原语所有属性的 3D 高斯的中间节点。例如保持它原本所有的特征：均值$\\mu$、协方差$\\Sigma$、透明度 $o$ 等等。 对于均值和协方差，有很多文献详尽的描述了这个混合过程。可以通过如下公式混合 $N$ 个在第 $l$ 级的均值为 $\\mu_i^l$，协方差为 $\\Sigma_i^l$ 高斯函数。我们可以通过评估这 $N$ 个高斯函数和待估计的高斯函数之间的 3D Kullback-Leibler divergence。3DKL 散度描述了两个高斯函数之间的相关性。那么显然的，假设$f = \\sum_{i=1}^{N}\\mathcal \\alpha_i N(\\mu_i, \\Sigma_i)$，g为我们所需要新的高斯函数，应该有： $$ d(f,g)=\\sum_{i=1}^k\\alpha_i\\min_{j=1}^mKL(f_i||g_j) $$ 即原始的混合高斯函数 $f = \\sum_{i=1}^{N}\\mathcal \\alpha_i N(\\mu_i, \\Sigma_i)$ 变为新估计的高斯函数 $g$ 的过程中所损失的信息最少，即上式有最小值。我们忽略推导过程，其结果应为： $$ \\begin{gather} \\mu^{(l+1)}=\\sum_i^Nw_i\\mu_i^{(l)}\\\\ \\Sigma^{(l+1)}=\\sum_i^Nw_i(\\Sigma_i^{(l)}+(\\mu_i^{(l)}-\\mu^{(l+1)})(\\mu_i^{(l)}-\\mu^{(l+1)})^T) \\end{gather} $$ 其中 $\\omega_i$ 为一个归一化系数，其定义为： $$ w_i = \\frac{w_i'}{\\sum_1^N w_i'} $$ 其中具体我们定义了非标准化的合并权值 $w_i'$，它们与每个子高斯对创建的父高斯的贡献成正比。事实上这个权重与传统的高斯混合模型中“属于该高斯函数的概率”这一参数有着相似的含义。我们不妨将三维高斯函数投影到二维相机空间上称为二维高斯（即带 $'$ 的参数所对应的）。考虑其中一个高斯函数$g_i$，其的参数为$c_i, o_i$，它对于在$(x,y)$的颜色 $C(x,y)$的贡献有： $$ C(x,y) = o_ic_iG(x,y) $$ 我们能投影到该点的全部高斯函数所产生的结果，应有： $$ \\begin{aligned}C_i\u0026=\\mathrm{~o_i~c_i}\\int_X\\int_YG(x,y)\\\\\u0026=\\mathrm{~o_i~c_i}\\sqrt{(2\\pi)^2|\\Sigma^{\\prime}|}\\end{aligned} $$ 考虑高斯函数的性质，我们可以作出如下简化假设：\n高斯函数几乎是各向同性的， 高斯函数有较少的重叠、透视失真。 在这个简化条件下，我们不妨先考虑两个高斯函数混合的情形，我们需要保证生成的高斯函数 $g_p$ 等于两个子函数$g_2,g_2$的和。这是一个很好的性质，相当于我们将原本按照体积渲染累计的高斯函数简化为一般的高斯高斯混合模型。那么忽略常数项，有： $$ w_i^{\\prime}=\\mathrm{~o_i}\\sqrt{|\\Sigma_i^{\\prime}|} $$ 在实践中，由于高斯二维协方差的行\t列式的平方根与相应的三维椭球的(投影)表面成正比，我们计算每个椭球的表面 $\\sqrt{\\det(\\Sigma_i)}$ 而不是 $\\sqrt{\\det(\\Sigma_i')}$。\n这样我们可以用这个混合参数来混合球谐系数： $$ SH^{(l+1)}=SH_1^{(l)}w_1+SH_2^{(l)}w_2. $$ 我们也可以使用权重来合并不透明度。然而，我们的合并策略改变了中间节点的不透明度属性的含义。\n可以看到，我们在将两个高斯函数混合为一个的过程中，可能会出现混合结果的值超过了1，然而我们需要将其限制为1，大于1的不透明度意味着不透明，当然这和不透明度为1有着相同的效果，但是这样的操作显然改变了不透明度的含义。事实上产生这样的结果主要是由两个高斯函数之间不是由严谨的体积渲染实现的，而是通过一定的简化假设变为高斯混合模型，这样的简化假设导致了不透明度含义的改变。在一些特别的场景中，高斯函数各向同性的假设无法成立，这在后面会有描述。\n我们现在有了将多个高斯函数混合成一个高斯函数的办法。在给定一组原始的 3DGS 场景上，我们首先可以在其上构建一个自顶向下的轴对齐的边界框 (axis-aligned bounding box) 边界体层次结构 (Bounding Volume Hierarchy) 。我们从一个包含所有高斯原语的AABB开始，使用3倍的存储大小来捕获它们的范围。初始AABB是BVH的根节点。为了获得子节点，我们在当前节点上递归地执行二进制中位数分割。首先，我们将一组中所有高斯函数的均值投影到它们的边界框的最长轴上。然后，我们根据其投影均值相对于所有投影中位数的位置分配每个原语来划分组。生成的BVH树确保每个内部节点的子节点在空间上是紧凑的。然后，我们从它们各自的子节点计算中间节点高斯，从叶子节点开始，递归地向上合并树。\n3.2. 层次切割选择和水平切换 对于一个给定的 3DGS 的分辨率层次树结构和一个视角$V$，我们需要找到一个对分辨率层次树的裁切，需要保证在保证渲染质量的同时最大程度的提高渲染的效率。我们首先定义我们首先将给定层次节点 $n$ 的粒度$\\epsilon(n)$，定义为给定视图在屏幕上的投影大小。\n具体来说，我们在节点中包含的叶子高斯上使用边界框，然后取边界框的最大维度并在这个纬度上计算投影大小。我们通过比较边界框的投影与一个该节点预设的粒度阈值（例如一个像素）来判断是否进行切割。例如对于 (b) 中的紫色节点，其显然包含着至少两个子节点——即蓝色和红色节点，这两个子节点各包含一个高斯函数。那么紫色节点的边界即位这两个子节点的高斯函数所包含的最大范围。基于生成的层级节点和他的边界，AABA方法可以保证它的夫节点一定不会比子节点小。这保证我们可以在线性时间可以完成这个计算。在大规模并行计算中，每个节点在恒定时间内完成：如果节点𝑛的边界满足粒度条件，但其子节点的边界不满足，则选择节点𝑛作为给定设置并将其包含在cut中（上图(b)中的绿色曲线）。请注意，该逻辑要么选择所有子节点，要么选择父节点。\n任何分层呈现解决方案的一个关键元素是允许分层级别之间平滑转换的能力。我们通过插值单个高斯属性来实现平滑过渡。当一个节点不再是当前粒度下最合适的分割时，它会被它的子节点代替。但是当该节点没有子节点时，可以通过在父节点和子节点间插值产生新节点。我们通过选择恰好超过粒度阈值 $\\epsilon$ 的节点作为裁切的结果。差值的权重通过该裁切中的每个节点的粒度 $\\epsilon(n)$ 以及粒度的变化趋势 $\\epsilon(p)$，其中 $p$ 是 $n$ 的父节点。插值的权重可以写作： $$ t_n=\\frac{\\tau_\\epsilon-\\epsilon(n)}{\\epsilon(p)-\\epsilon(n)}. $$ 位置（均值）、协方差、颜色可以通过这个插值系数线性的计算出来。对于协方差，即便对旋转使用线性插值而不是更昂贵的“球面插值”，分别插值尺度和旋转也会产生比直接对协方差矩阵插值更好的效果。但是有时高斯函数的旋转和缩放上并不相同，但是有着相同的协方差矩阵。\n如 (a) 所示，左右两个高斯函数有着相同的协方差；但是其x-y坐标有90度的旋转，其旋转和缩放显然是不同的。因此，在直接插值它们的属性时，意料之外的旋转会产生视觉上的干扰。例如上述两个协方差插值时，我们希望得到的高斯函数的方向应与之是相同的，如果直接插值可能会产生一个与之成45度的并不合理的协方差矩阵。\n为了避免这种情况，在层次结构生成过程中，我们还执行方向匹配：从根节点开始，我们递归地重新定义每个子高斯的方向轴，让他们之间的旋转有最小值。具体来说我们旋转每一个节点的高斯函数，并计算其与父节点的角度差，最终选取角度差最小的作为其旋转轴。\n对于不透明度的处理也需要一些技巧。在从父节点到子节点的转化过程中，子节点分享了父节点的全部参数，这些属性逐渐地通过插值的方式分享到每个子节点中去。那么显然的，我们需要让生成的两个子节点按照体渲染的方式混合后的结果应和父节点相同。思考最简单的两个子节点和一个孤立的父节点的问题，应有父节点对颜色混合的贡献$\\alpha_pc_p$，我们需要找到对子节点的权重$\\alpha'$： $$ \\alpha_pc_p=\\alpha^{\\prime}c_p+(1-\\alpha^{\\prime})\\alpha^{\\prime}c_p $$ 因此子节点的颜色就会父节点的颜色，应有： $$ \\alpha^{\\prime}=1-\\sqrt{1-\\alpha_p} $$使用权重$\\alpha'$，我们可以像其他参数一样使用线性插值从其父节点计算子节点的混合系数 $\\alpha$ $$ \\alpha(t)=t\\alpha_i+(1-t)\\alpha^{\\prime} $$ 通过这种插值方案，我们实现了层次结构的平滑过渡。下图中说明了两个不同目标粒度的层次结构的结果渲染：\n4. 优化和结构层次压缩 3DGS的层次结构由集合基元的集合构成，最终我们需要更加明确清晰考虑场景的外观。因为层次结构的每个中间节点本身就是一个三维高斯基元，它就可以通过优化的方式提升其视觉质量。为了做到这一点，我们需要通过中间节点来传播梯度，引入一个其中间节点可以被优化的层次结构。下面我们将介绍这是如何实现的，还引入一个额外的步骤来压缩层次结果。\n图形学中传统的层次 LOD 算法往往是为了在远处观察时实现一个简化版本的场景。我们前面介绍的粒度阈值通过计算在屏幕上投影的粒度了实现了这一效果。\n4.1. 层次结构的优化 我们自顶向下的层次结构构造产生了一个运行良好的数据结构。一旦完成了构件，中间层级的节点就可以像叶节点一样优化。因此我们可以通过层次结构中的中间节点来提高整体的视觉质量。那么问题在于如何在不同的规模间进行优化。一个优化层次结构的方案是随机选取一个输入的照片和一个降采样系数，较低的分辨率自然意味着较低的粒度，对应于结构层次中的裁剪。但是这种方法有显然的缺点：当降低分辨率时，低频细节无法保存。\n在优化过程中，我们并不降低分辨率，而是直接渲染最高分辨率的照片并随机的选择颗粒度阈值。这具有在许多不同切割中优化节点的预期效果，同时保留视觉细节。当我们拥有有限的资源时，这将非常有用，因为我们可以在保持更好的视觉质量的同时应用更积极的LOD策略。\n具体来说，我们直接加载生成的层次结构，选择一个训练视角并在一个给定的区间内选择粒度阈值 $\\tau_\\epsilon$来训练。这个目标阈值的区间可以写作： $$ [\\tau_{min}, \\tau_{max}) $$ 训练视角的选择对应来所选择的裁切，为了实现对所有结构层级进行有效的采样，我们的采样粒度阈值 $\\tau_\\epsilon$ 由一个均匀随机变量$\\xi\\in[0,1]$定义，有： $$ \\tau_\\epsilon = \\tau_{max}^\\xi \\tau_{min}^{1-\\xi} $$ 裁切和插值在训练过程中均有使用，为了同时优化子节点和父节点并使用平滑切换，我们需要将梯度合理的传播到该节点临近的两层，从而同时优化父节点和子节点。这要求我们能通过插值权重和不透明度混合的权重$\\alpha'$的表达式来传递梯度。通过优化层次结构的多个级别，我们解决了一个比3DGS更复杂的问题：优化更高的LOD级别也可能由于插值而降低叶子的质量。为了避免这种情况，我们在优化过程中不改变叶节点。\n原始的3DGS无法很好的处理频域混叠的问题，由于层次结构可以工作在不同的尺度上，正确的抗混叠是十分重要的，本文中会使用 EWA 滤波器来滤出高频混叠。\n4.2. 结构层次压缩 结构层次增加了内存上的开销。更重要的是，为了进行优化层次结构，我们希望避免父节点只比子节点大一点点的情况出现。如果这种情况出现，由于其粒度差别很小，着可能会导致在训练过程中起很少被选中进行优化。为了避免这一点，我们对生成的结构层次树进行稀疏化。\n首先我们标记所有叶节点，即所有3DGS优化产生的节点，他们在裁切过程中不应该被删除。之后我们我们在所有训练视图上找到最小目标粒度 $\\tau_{min}=3$ 中的切割构成一个集合。然后，我们在这个集合中找到最底部的节点，这再次产生一个切割。这些节点被认为是与所选粒度相关的最相近的节点，它们之间的所有节点和已经标记的节点都从树中删除。然后我们将目标的粒度提高 $2$ 倍并重复这个过程知道达到 $\\tau_{max}$，达到图像分辨率的一半。\n5. 大场景训练 我们现在可以建立三维高斯函数的有效层次结构；这些对于处理非常大的场景是必不可少的，因为从远处看到的场景部分可以在更粗的层次结构中渲染。为了训练大型场景，我们建立了用于实时渲染大数据的通用计算机图形学方法。特别是，我们通过将大型场景细分为块来引入分而治之的方法。\n对于捕获的场景，我们将块大小定义为 $50\\times50 \\rm m$，对于用车辆捕获的场景，我们将块大小定义为 $100\\times100 \\rm m$。虽然大小有限，但这些块仍然比原始 3DGS 方法能处理的能力大。此外，这种场景的捕获风格必然比大多数亮度场解决方案所期望的要稀疏得多。因此，我们调整了三维高斯函数的优化来考虑这些差异。\n我们的目标是允许并行处理单个块，在给定足够计算资源的情况下，允许在合理的时钟时间内处理大型场景。但是单独处理可能会导致重合部分的不一致，在每个单独的块中完成处理后，需要一个整合步骤来处理这些差异。\n5.1. 粗初始化和块细分 为了使所有部分的训练一致，我们需要为所有后续步骤提供一个基本框架和天空盒。为了使所有部分的训练一致，我们需要为所有后续步骤提供一个基本框架和天空盒。我们通过对整个数据集进行非常粗略的初始优化来实现这一点。具体来说，我们使用可用的 SfM 点启动整个场景的默认3DGS优化，并添加一个辅助的天空盒。这个粗略模型作为提供背景细节的最小基础，即场景中给定部分之外的部分。在极大场景的情况下，如果存储SfM点会超出RAM容量，粗略优化本身可以分成多个步骤进行，部分中间结果会被流式传输到磁盘。我们将场景划分为足够大的块，以便为常见的现实世界元素（包括汽车、建筑物和纪念碑）建立足够的上下文。对于每个块，我们选择所有在块范围内或在块范围的2倍以内且在块范围内有超过50个SfM点的摄像机。\n5.2. 块尺度的训练 我们对每个块独立进行训练；然后将结果用于为每个块创建层次结构，随后进行优化和整合步骤。在大型数据集中，典型的块与原始3DGS设置中使用的数据有显著不同。特别是，场景的范围显著大于Mip-NeRF 360等数据集的小场景。此外，捕获密度也要低得多，而且不是“以物体为中心”的。这使得优化更加困难，因为光线空间没有均匀覆盖。数据还包含曝光变化、人类和需要在优化中去除和忽略的移动物体（如汽车、自行车等）。\n我们定义了一个围绕场景范围的天空盒，即在直径为场景十倍的球体上放置100,000个3DGS基元以捕获天空的效果。我们加载场景的粗略优化结果，这将用于块之外的所有内容；这也防止了每个块在天空上生成不一致的内容。我们使用3DGS优化方法和正确的抗锯齿技术来训练块内的内容。我们对块外的粗略环境和天空盒进行小范围的临时优化，特别是仅优化不透明度和SH系数。\n原始的3DGS优化通过收集统计数据来决定是否在固定间隔内对高斯进行稠密化。具体来说，稠密化策略基于固定次数迭代中屏幕空间位置梯度的平均值。然而，在无界场景中存在两个主要问题。首先，这一策略很少阻止高斯稠密化，无论它们是否足够精细以建模局部细节。其次，具有稀疏、分散摄像机的数据集（例如城市穿越捕捉的情况）总体上稠密化的倾向更低。我们通过将稠密化策略改为考虑观察到的屏幕空间梯度的最大值而不是其平均值来解决这两个问题，这在稀疏捕捉的情况下不再可靠。我们拥有的稀疏摄像机捕捉不足以提供高质量的重建信息，例如在城市驾驶场景中的街道。我们进行单目深度预测，基于SfM点缩放和移动深度，并使用它来正则化优化。这改善了视觉质量，特别是对于道路。\n5.3. 块整合和渲染 每个块从COLMAP的每块细化处理中获取SfM点，以及其相邻块中基本框架中包含的3D高斯。与一个块及其层次结构相关的3D高斯因此有时会位于块本身之外。在整合阶段，如果与块 $i$ 相关但位于块外的原语更接近另一个块$j\\neq i$，则将其删除。整合还会创建一个具有整个场景根节点的全局层次结构。渲染是通过设置粒度阈值并找到相应的剪切点来执行的。我们每2帧更新一次剪切点，通过从CPU RAM传输节点到GPU来添加细节，并每100帧进行一次清理。\n6. 附录 6.1. 如何降低高斯混合模型的复杂度 假设我们有一个分布，其由 $k$ 个 $d$ 纬高斯函数的高斯混合模型构成，可以写作： $$ f(y)=\\sum_{i=1}^k\\alpha_iN(y;\\mu_i,\\Sigma_i)=\\sum_{i=1}^k\\alpha_if_i(y) $$ 我们希望找到另一个高斯混合模型 $g(y)$，有： $$ g(y) = \\sum_{i=1}^{m}\\beta_ig_i(y) $$ 其中$m",
  "wordCount" : "301",
  "inLanguage": "en",
  "image": "https://wangjv0812.github.io/WangJV-Blog-Pages/","datePublished": "2024-07-08T16:40:25+08:00",
  "dateModified": "2024-07-08T16:40:25+08:00",
  "author":{
    "@type": "Person",
    "name": "WangJV"
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://wangjv0812.github.io/WangJV-Blog-Pages/2024/07/hierarchical-gaussian-splatting/"
  },
  "publisher": {
    "@type": "Organization",
    "name": "WangJV Blog",
    "logo": {
      "@type": "ImageObject",
      "url": "https://wangjv0812.github.io/WangJV-Blog-Pages/favicon.ico"
    }
  }
}
</script>
</head>

<body class="" id="top">
<script>
    if (localStorage.getItem("pref-theme") === "dark") {
        document.body.classList.add('dark');
    } else if (localStorage.getItem("pref-theme") === "light") {
        document.body.classList.remove('dark')
    } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
        document.body.classList.add('dark');
    }

</script>

<header class="header">
    <nav class="nav">
        <div class="logo">
            <a href="https://wangjv0812.github.io/WangJV-Blog-Pages/" accesskey="h" title="WangJV Blog (Alt + H)">WangJV Blog</a>
            <div class="logo-switches">
                <button id="theme-toggle" accesskey="t" title="(Alt + T)" aria-label="Toggle theme">
                    <svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
                        fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                        stroke-linejoin="round">
                        <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
                    </svg>
                    <svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
                        fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                        stroke-linejoin="round">
                        <circle cx="12" cy="12" r="5"></circle>
                        <line x1="12" y1="1" x2="12" y2="3"></line>
                        <line x1="12" y1="21" x2="12" y2="23"></line>
                        <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
                        <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
                        <line x1="1" y1="12" x2="3" y2="12"></line>
                        <line x1="21" y1="12" x2="23" y2="12"></line>
                        <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
                        <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
                    </svg>
                </button>
            </div>
        </div>
        <ul id="menu">
            <li>
                <a href="https://wangjv0812.github.io/WangJV-Blog-Pages/" title="Home">
                    <span>Home</span>
                </a>
            </li>
            <li>
                <a href="https://wangjv0812.github.io/WangJV-Blog-Pages/posts/" title="Posts">
                    <span>Posts</span>
                </a>
            </li>
            <li>
                <a href="https://wangjv0812.github.io/WangJV-Blog-Pages/archives/" title="Archive">
                    <span>Archive</span>
                </a>
            </li>
            <li>
                <a href="https://wangjv0812.github.io/WangJV-Blog-Pages/tags/" title="Tags">
                    <span>Tags</span>
                </a>
            </li>
            <li>
                <a href="https://wangjv0812.github.io/WangJV-Blog-Pages/search/" title="🔍 Search (Alt &#43; /)" accesskey=/>
                    <span>🔍 Search</span>
                </a>
            </li>
        </ul>
    </nav>
</header>
<main class="main">

<article class="post-single">
  <header class="post-header">
    <div class="breadcrumbs"><a href="https://wangjv0812.github.io/WangJV-Blog-Pages/">Home</a>&nbsp;»&nbsp;<a href="https://wangjv0812.github.io/WangJV-Blog-Pages/posts/">Posts</a></div>
    <h1 class="post-title entry-hint-parent">
      Hierarchical Gaussian Splatting
    </h1>
    <div class="post-meta"><span title='2024-07-08 16:40:25 +0800 CST'>July 8, 2024</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;301 words&nbsp;·&nbsp;WangJV&nbsp;|&nbsp;<a href="https://github.com/WangJV0812/WangJV-Blog-Source/tree/master/content/posts/Hierarchical%20Gaussian%20Splatting/index.md" rel="noopener noreferrer edit" target="_blank">Suggest Changes</a>

</div>
  </header> <div class="toc">
    <details >
        <summary accesskey="c" title="(Alt + C)">
            <span class="details">Table of Contents</span>
        </summary>

        <div class="inner"><nav id="TableOfContents">
  <ul>
    <li><a href="#1-abstract--introduction">1. Abstract &amp; Introduction</a></li>
    <li><a href="#2-概述和背景">2. 概述和背景</a>
      <ul>
        <li><a href="#21-背景">2.1. 背景</a></li>
      </ul>
    </li>
    <li><a href="#3-3dgaussian-的结构化-hierarchy-的细节层次-lod">3. 3DGaussian 的结构化 (hierarchy) 的细节层次 (LOD)</a>
      <ul>
        <li><a href="#31-生成不同分辨率的高斯球">3.1. 生成不同分辨率的高斯球</a></li>
        <li><a href="#32-层次切割选择和水平切换">3.2. 层次切割选择和水平切换</a></li>
      </ul>
    </li>
    <li><a href="#4-优化和结构层次压缩">4. 优化和结构层次压缩</a>
      <ul>
        <li><a href="#41-层次结构的优化">4.1. 层次结构的优化</a></li>
        <li><a href="#42-结构层次压缩">4.2. 结构层次压缩</a></li>
      </ul>
    </li>
    <li><a href="#5-大场景训练">5. 大场景训练</a>
      <ul>
        <li><a href="#51-粗初始化和块细分">5.1. 粗初始化和块细分</a></li>
        <li><a href="#52-块尺度的训练">5.2. 块尺度的训练</a></li>
        <li><a href="#53-块整合和渲染">5.3. 块整合和渲染</a></li>
      </ul>
    </li>
    <li><a href="#6-附录">6. 附录</a>
      <ul>
        <li><a href="#61-如何降低高斯混合模型的复杂度">6.1. 如何降低高斯混合模型的复杂度</a></li>
      </ul>
    </li>
    <li><a href="#参考">参考</a></li>
  </ul>
</nav>
        </div>
    </details>
</div>

  <div class="post-content"><h2 id="1-abstract--introduction">1. Abstract &amp; Introduction<a hidden class="anchor" aria-hidden="true" href="#1-abstract--introduction">#</a></h2>
<p>3D Gaussian Splatting 面临着一个几乎看起来无法规避的问题，就是我们需要给每个高斯函数分配一定的存储空间，并在训练时对其优化；并且在训练和渲染时需要同时将所有的高斯函数加载到设备的现存中，这导致训练和渲染在计算上是十分昂贵的。这导致我们总是要在渲染、重建质量和速度之间作出权衡，甚至很多时候是没办法训练的。这制约了 Splatting 在大场景的工作（例如城市级）上的应用。</p>
<p>那么一个很显然的想法，就是在较远时提供一个较低的分辨率，实现一个分层级的渲染和训练，并且只加载视角可见的部分。那么需要的方法有两点：</p>
<ol>
<li>引入结构层次（Hierarchy），使用一种高效细节级别解决方案（Level of Detial）。</li>
<li>引入分置策略（divide-and-conquer），让我们可以在独立的训练和渲染每一个小块。</li>
</ol>
<p>同时，通过不同层级的结构（Guassian Function）可以用来优化中间层的高斯函数。这篇文章所提出的策略可以实时的渲染非常大的场景，覆盖长达几公里的轨迹，持续长达一小时。</p>
<p><img alt="db286f9b0b818bd938a3ef6ea35d1c7a_0_Figure_1_-1273433434" loading="lazy" src="https://wangjv0812.github.io/WangJV-Blog-Pages/2024/07/hierarchical-gaussian-splatting/images/db286f9b0b818bd938a3ef6ea35d1c7a_0_Figure_1_-1273433434.png"></p>
<h2 id="2-概述和背景">2. 概述和背景<a hidden class="anchor" aria-hidden="true" href="#2-概述和背景">#</a></h2>
<h3 id="21-背景">2.1. 背景<a hidden class="anchor" aria-hidden="true" href="#21-背景">#</a></h3>
<p>3DGS 提供了一种基于体积基元的空间场景表达方法，每个体积基元含有如下特征：</p>
<ol>
<li>位置（或者说均值$\mu$）</li>
<li>协方差矩阵$\Sigma$</li>
<li>透明度（$o$）</li>
<li>球谐系数（$SH$）用于表达与视角相关的颜色，或者直接使用颜色</li>
</ol>
<p>三维基元可以投影到二维屏幕空间上，并且通过 $\alpha\text{-blander}$ 来实现光栅化。 $\alpha\text{-blander}$ 的权重为：
</p>
$$
\begin{aligned}
\alpha &= \text{oG}\\
G(x,y) &= \exp 
\left\{
-\frac 12 ([x,y]^T-\mu')^T\Sigma'^{-1}([x,y]^T-\mu')
\right\}
\end{aligned}
$$<p>
其中 $\mu'$ 是三维空间基元投影到二维相机平面上基元的均值，$\Sigma'$ 投影的二维基元的协方差。</p>
<h2 id="3-3dgaussian-的结构化-hierarchy-的细节层次-lod">3. 3DGaussian 的结构化 (hierarchy) 的细节层次 (LOD)<a hidden class="anchor" aria-hidden="true" href="#3-3dgaussian-的结构化-hierarchy-的细节层次-lod">#</a></h2>
<p>在处理大型场景以允许有效渲染大量内容时，细节级别 (LOD) 解决方案至关重要；因此，我们的目标是创建一个层次结构，表示原始 3DGS 优化生成的原语。遵循图形中的传统LOD方法，我们需要</p>
<ol>
<li>找到候选3DGS基元，并定义如何将它们合并到中间节点</li>
<li>提供一种有效的方法来确定层次结构中的切割，从而在质量和速度之间提供良好的折衷</li>
<li>层次结构级别之间的平滑过渡策略</li>
</ol>
<h3 id="31-生成不同分辨率的高斯球">3.1. 生成不同分辨率的高斯球<a hidden class="anchor" aria-hidden="true" href="#31-生成不同分辨率的高斯球">#</a></h3>
<p>我们为每个块创建一个具有内部节点和叶节点的基于树的层次结构。每个节点都与一个 3D 高斯相关联，该高斯要么是来自原始优化的叶节点，要么是合并的内部节点。我们对中间节点的要求是它们应该：</p>
<ol>
<li>保持与叶节点相同的快速光栅化例程</li>
<li>尽可能准确地表示子节点的外观。因此，我们需要定义具有 3DGS 原语所有属性的 3D 高斯的中间节点。例如保持它原本所有的特征：均值$\mu$、协方差$\Sigma$、透明度 $o$ 等等。</li>
</ol>
<p>对于均值和协方差，有很多文献详尽的描述了这个混合过程。可以通过如下公式混合 $N$ 个在第 $l$ 级的均值为 $\mu_i^l$，协方差为 $\Sigma_i^l$ 高斯函数。我们可以通过评估这 $N$ 个高斯函数和待估计的高斯函数之间的 3D Kullback-Leibler divergence。3DKL 散度描述了两个高斯函数之间的相关性。那么显然的，假设$f = \sum_{i=1}^{N}\mathcal \alpha_i N(\mu_i, \Sigma_i)$，g为我们所需要新的高斯函数，应该有：
</p>
$$
d(f,g)=\sum_{i=1}^k\alpha_i\min_{j=1}^mKL(f_i||g_j)
$$<p>
即原始的混合高斯函数 $f = \sum_{i=1}^{N}\mathcal \alpha_i N(\mu_i, \Sigma_i)$ 变为新估计的高斯函数 $g$ 的过程中所损失的信息最少，即上式有最小值。我们忽略推导过程，其结果应为：
</p>
$$
\begin{gather}
\mu^{(l+1)}=\sum_i^Nw_i\mu_i^{(l)}\\
\Sigma^{(l+1)}=\sum_i^Nw_i(\Sigma_i^{(l)}+(\mu_i^{(l)}-\mu^{(l+1)})(\mu_i^{(l)}-\mu^{(l+1)})^T)
\end{gather}
$$<p>
其中 $\omega_i$ 为一个归一化系数，其定义为：
</p>
$$
w_i = \frac{w_i'}{\sum_1^N w_i'}
$$<p>
其中具体我们定义了非标准化的合并权值 $w_i'$，它们与每个子高斯对创建的父高斯的贡献成正比。事实上这个权重与传统的高斯混合模型中“属于该高斯函数的概率”这一参数有着相似的含义。我们不妨将三维高斯函数投影到二维相机空间上称为二维高斯（即带 $'$ 的参数所对应的）。考虑其中一个高斯函数$g_i$，其的参数为$c_i, o_i$，它对于在$(x,y)$的颜色 $C(x,y)$的贡献有：
</p>
$$
C(x,y) = o_ic_iG(x,y)
$$<p>
我们能投影到该点的全部高斯函数所产生的结果，应有：
</p>
$$
\begin{aligned}C_i&=\mathrm{~o_i~c_i}\int_X\int_YG(x,y)\\&=\mathrm{~o_i~c_i}\sqrt{(2\pi)^2|\Sigma^{\prime}|}\end{aligned}
$$<p>
考虑高斯函数的性质，我们可以作出如下简化假设：</p>
<ol>
<li>高斯函数几乎是各向同性的，</li>
<li>高斯函数有较少的重叠、透视失真。</li>
</ol>
<p>在这个简化条件下，我们不妨先考虑两个高斯函数混合的情形，我们需要保证生成的高斯函数 $g_p$ 等于两个子函数$g_2,g_2$的和。这是一个很好的性质，相当于我们将原本按照体积渲染累计的高斯函数简化为一般的高斯高斯混合模型。那么忽略常数项，有：
</p>
$$
w_i^{\prime}=\mathrm{~o_i}\sqrt{|\Sigma_i^{\prime}|}
$$<p>
在实践中，由于高斯二维协方差的行	列式的平方根与相应的三维椭球的(投影)表面成正比，我们计算每个椭球的表面 $\sqrt{\det(\Sigma_i)}$ 而不是 $\sqrt{\det(\Sigma_i')}$。</p>
<p>这样我们可以用这个混合参数来混合球谐系数：
</p>
$$
SH^{(l+1)}=SH_1^{(l)}w_1+SH_2^{(l)}w_2.
$$<p>
我们也可以使用权重来合并不透明度。然而，我们的合并策略改变了中间节点的不透明度属性的含义。</p>
<img src="./images/db286f9b0b818bd938a3ef6ea35d1c7a_3_Figure_2_-1355340760.png" alt="db286f9b0b818bd938a3ef6ea35d1c7a_3_Figure_2_-1355340760" style="zoom:60%;" />
<p>可以看到，我们在将两个高斯函数混合为一个的过程中，可能会出现混合结果的值超过了1，然而我们需要将其限制为1，大于1的不透明度意味着不透明，当然这和不透明度为1有着相同的效果，但是这样的操作显然改变了不透明度的含义。事实上产生这样的结果主要是由两个高斯函数之间不是由严谨的体积渲染实现的，而是通过一定的简化假设变为高斯混合模型，这样的简化假设导致了不透明度含义的改变。在一些特别的场景中，高斯函数各向同性的假设无法成立，这在后面会有描述。</p>
<p>我们现在有了将多个高斯函数混合成一个高斯函数的办法。在给定一组原始的 3DGS 场景上，我们首先可以在其上构建一个自顶向下的轴对齐的边界框 (axis-aligned bounding box) 边界体层次结构 (Bounding Volume Hierarchy) 。我们从一个包含所有高斯原语的AABB开始，使用3倍的存储大小来捕获它们的范围。初始AABB是BVH的根节点。为了获得子节点，我们在当前节点上递归地执行二进制中位数分割。首先，我们将一组中所有高斯函数的均值投影到它们的边界框的最长轴上。然后，我们根据其投影均值相对于所有投影中位数的位置分配每个原语来划分组。生成的BVH树确保每个内部节点的子节点在空间上是紧凑的。然后，我们从它们各自的子节点计算中间节点高斯，从叶子节点开始，递归地向上合并树。</p>
<h3 id="32-层次切割选择和水平切换">3.2. 层次切割选择和水平切换<a hidden class="anchor" aria-hidden="true" href="#32-层次切割选择和水平切换">#</a></h3>
<p>对于一个给定的 3DGS 的分辨率层次树结构和一个视角$V$，我们需要找到一个对分辨率层次树的裁切，需要保证在保证渲染质量的同时最大程度的提高渲染的效率。我们首先定义我们首先将给定层次节点 $n$ 的粒度$\epsilon(n)$，定义为给定视图在屏幕上的投影大小。</p>
<img src="./images/db286f9b0b818bd938a3ef6ea35d1c7a_4_Figure_3_490331763.png" alt="db286f9b0b818bd938a3ef6ea35d1c7a_4_Figure_3_490331763" style="zoom:67%;" />
<p>具体来说，我们在<strong>节点中包含的叶子高斯</strong>上使用边界框，然后取边界框的最大维度并在这个纬度上计算投影大小。我们通过比较边界框的投影与一个该节点预设的粒度阈值（例如一个像素）来判断是否进行切割。例如对于 (b) 中的紫色节点，其显然包含着至少两个子节点——即蓝色和红色节点，这两个子节点各包含一个高斯函数。那么紫色节点的边界即位这两个子节点的高斯函数所包含的最大范围。基于生成的层级节点和他的边界，AABA方法可以保证它的夫节点一定不会比子节点小。这保证我们可以在线性时间可以完成这个计算。在大规模并行计算中，每个节点在恒定时间内完成：<strong>如果节点𝑛的边界满足粒度条件，但其子节点的边界不满足，则选择节点𝑛作为给定设置并将其包含在cut中（上图(b)中的绿色曲线）</strong>。请注意，该逻辑要么选择所有子节点，要么选择父节点。</p>
<p>任何分层呈现解决方案的一个关键元素是允许分层级别之间平滑转换的能力。我们通过插值单个高斯属性来实现平滑过渡。当一个节点不再是当前粒度下最合适的分割时，它会被它的子节点代替。但是当该节点没有子节点时，可以通过在父节点和子节点间插值产生新节点。我们通过选择恰好超过粒度阈值 $\epsilon$ 的节点作为裁切的结果。差值的权重通过该裁切中的每个节点的粒度 $\epsilon(n)$ 以及粒度的变化趋势 $\epsilon(p)$，其中 $p$ 是 $n$ 的父节点。插值的权重可以写作：
</p>
$$
t_n=\frac{\tau_\epsilon-\epsilon(n)}{\epsilon(p)-\epsilon(n)}.
$$<p>
位置（均值）、协方差、颜色可以通过这个插值系数线性的计算出来。对于协方差，即便对旋转使用线性插值而不是更昂贵的“球面插值”，<strong>分别插值尺度和旋转也会产生比直接对协方差矩阵插值更好的效果</strong>。但是有时高斯函数的旋转和缩放上并不相同，但是有着相同的协方差矩阵。</p>
<img src="./images/db286f9b0b818bd938a3ef6ea35d1c7a_4_Figure_4_1478400070.png" alt="db286f9b0b818bd938a3ef6ea35d1c7a_4_Figure_4_1478400070" style="zoom: 75%;" />
<p>如 (a) 所示，左右两个高斯函数有着相同的协方差；但是其x-y坐标有90度的旋转，其旋转和缩放显然是不同的。因此，在直接插值它们的属性时，意料之外的旋转会产生视觉上的干扰。例如上述两个协方差插值时，我们希望得到的高斯函数的方向应与之是相同的，如果直接插值可能会产生一个与之成45度的并不合理的协方差矩阵。</p>
<p>为了避免这种情况，在层次结构生成过程中，我们还执行方向匹配：从根节点开始，我们递归地重新定义每个子高斯的方向轴，让他们之间的旋转有最小值。具体来说我们旋转每一个节点的高斯函数，并计算其与父节点的角度差，最终选取角度差最小的作为其旋转轴。</p>
<p>对于不透明度的处理也需要一些技巧。在从父节点到子节点的转化过程中，子节点分享了父节点的全部参数，这些属性逐渐地通过插值的方式分享到每个子节点中去。那么显然的，<strong>我们需要让生成的两个子节点按照体渲染的方式混合后的结果应和父节点相同</strong>。思考最简单的两个子节点和一个孤立的父节点的问题，应有父节点对颜色混合的贡献$\alpha_pc_p$，我们需要找到对子节点的权重$\alpha'$：
</p>
$$
\alpha_pc_p=\alpha^{\prime}c_p+(1-\alpha^{\prime})\alpha^{\prime}c_p
$$<p>
因此子节点的颜色就会父节点的颜色，应有：
</p>
$$
\alpha^{\prime}=1-\sqrt{1-\alpha_p}
$$<p>使用权重$\alpha'$，我们可以像其他参数一样使用线性插值从其父节点计算子节点的混合系数 $\alpha$
</p>
$$
\alpha(t)=t\alpha_i+(1-t)\alpha^{\prime}
$$<p>
通过这种插值方案，我们实现了层次结构的平滑过渡。下图中说明了两个不同目标粒度的层次结构的结果渲染：</p>
<p><img alt="db286f9b0b818bd938a3ef6ea35d1c7a_5_Figure_5_1643156070" loading="lazy" src="https://wangjv0812.github.io/WangJV-Blog-Pages/2024/07/hierarchical-gaussian-splatting/images/db286f9b0b818bd938a3ef6ea35d1c7a_5_Figure_5_1643156070.png"></p>
<h2 id="4-优化和结构层次压缩">4. 优化和结构层次压缩<a hidden class="anchor" aria-hidden="true" href="#4-优化和结构层次压缩">#</a></h2>
<p>3DGS的层次结构由集合基元的集合构成，最终我们需要更加明确清晰考虑场景的外观。因为层次结构的每个中间节点本身就是一个三维高斯基元，它就可以通过优化的方式提升其视觉质量。为了做到这一点，我们需要通过中间节点来传播梯度，引入一个其中间节点可以被优化的层次结构。下面我们将介绍这是如何实现的，还引入一个额外的步骤来压缩层次结果。</p>
<img src="./images/db286f9b0b818bd938a3ef6ea35d1c7a_5_Figure_6_-1514308536.png" alt="db286f9b0b818bd938a3ef6ea35d1c7a_5_Figure_6_-1514308536" style="zoom:60%;" />
<p>图形学中传统的层次 LOD 算法往往是为了在远处观察时实现一个简化版本的场景。我们前面介绍的粒度阈值通过计算在屏幕上投影的粒度了实现了这一效果。</p>
<h3 id="41-层次结构的优化">4.1. 层次结构的优化<a hidden class="anchor" aria-hidden="true" href="#41-层次结构的优化">#</a></h3>
<p>我们自顶向下的层次结构构造产生了一个运行良好的数据结构。一旦完成了构件，中间层级的节点就可以像叶节点一样优化。因此我们可以通过层次结构中的中间节点来提高整体的视觉质量。那么问题在于如何在不同的规模间进行优化。一个优化层次结构的方案是随机选取一个输入的照片和一个降采样系数，较低的分辨率自然意味着较低的粒度，对应于结构层次中的裁剪。但是这种方法有显然的缺点：当降低分辨率时，低频细节无法保存。</p>
<img src="./images/image-20240711143251810.png" alt="image-20240711143251810" style="zoom:40%;" />
<p>在优化过程中，我们并不降低分辨率，而是直接渲染最高分辨率的照片并随机的选择颗粒度阈值。这具有在许多不同切割中优化节点的预期效果，同时保留视觉细节。当我们拥有有限的资源时，这将非常有用，因为我们可以在保持更好的视觉质量的同时应用更积极的LOD策略。</p>
<p>具体来说，我们直接加载生成的层次结构，选择一个训练视角并在一个给定的区间内选择粒度阈值 $\tau_\epsilon$来训练。这个目标阈值的区间可以写作：
</p>
$$
[\tau_{min}, \tau_{max})
$$<p>
训练视角的选择对应来所选择的裁切，为了实现对所有结构层级进行有效的采样，我们的采样粒度阈值 $\tau_\epsilon$ 由一个均匀随机变量$\xi\in[0,1]$定义，有：
</p>
$$
\tau_\epsilon = \tau_{max}^\xi \tau_{min}^{1-\xi} 
$$<p>
裁切和插值在训练过程中均有使用，为了同时优化子节点和父节点并使用平滑切换，我们需要将梯度合理的传播到该节点临近的两层，从而同时优化父节点和子节点。这要求我们能通过插值权重和不透明度混合的权重$\alpha'$的表达式来传递梯度。通过优化层次结构的多个级别，我们解决了一个比3DGS更复杂的问题：优化更高的LOD级别也可能由于插值而降低叶子的质量。为了避免这种情况，我们在优化过程中不改变叶节点。</p>
<p>原始的3DGS无法很好的处理频域混叠的问题，由于层次结构可以工作在不同的尺度上，正确的抗混叠是十分重要的，本文中会使用 EWA 滤波器来滤出高频混叠。</p>
<h3 id="42-结构层次压缩">4.2. 结构层次压缩<a hidden class="anchor" aria-hidden="true" href="#42-结构层次压缩">#</a></h3>
<p>结构层次增加了内存上的开销。更重要的是，为了进行优化层次结构，我们希望避免父节点只比子节点大一点点的情况出现。如果这种情况出现，由于其粒度差别很小，着可能会导致在训练过程中起很少被选中进行优化。为了避免这一点，我们对生成的结构层次树进行稀疏化。</p>
<p>首先我们标记所有叶节点，即所有3DGS优化产生的节点，他们在裁切过程中不应该被删除。之后我们我们在所有训练视图上找到最小目标粒度 $\tau_{min}=3$ 中的切割构成一个集合。然后，我们在这个集合中找到最底部的节点，这再次产生一个切割。这些节点被认为是与所选粒度相关的最相近的节点，它们之间的所有节点和已经标记的节点都从树中删除。然后我们将目标的粒度提高 $2$ 倍并重复这个过程知道达到 $\tau_{max}$，达到图像分辨率的一半。</p>
<h2 id="5-大场景训练">5. 大场景训练<a hidden class="anchor" aria-hidden="true" href="#5-大场景训练">#</a></h2>
<p>我们现在可以建立三维高斯函数的有效层次结构；这些对于处理非常大的场景是必不可少的，因为从远处看到的场景部分可以在更粗的层次结构中渲染。为了训练大型场景，我们建立了用于实时渲染大数据的通用计算机图形学方法。特别是，我们通过将大型场景细分为块来引入分而治之的方法。</p>
<p>对于捕获的场景，我们将块大小定义为 $50\times50 \rm m$，对于用车辆捕获的场景，我们将块大小定义为 $100\times100 \rm m$。虽然大小有限，但这些块仍然比原始 3DGS 方法能处理的能力大。此外，这种场景的捕获风格必然比大多数亮度场解决方案所期望的要稀疏得多。因此，我们调整了三维高斯函数的优化来考虑这些差异。</p>
<p>我们的目标是允许并行处理单个块，在给定足够计算资源的情况下，允许在合理的时钟时间内处理大型场景。但是单独处理可能会导致重合部分的不一致，在每个单独的块中完成处理后，需要一个整合步骤来处理这些差异。</p>
<h3 id="51-粗初始化和块细分">5.1. 粗初始化和块细分<a hidden class="anchor" aria-hidden="true" href="#51-粗初始化和块细分">#</a></h3>
<p>为了使所有部分的训练一致，我们需要为所有后续步骤提供一个基本框架和天空盒。为了使所有部分的训练一致，我们需要为所有后续步骤提供一个基本框架和天空盒。我们通过对整个数据集进行非常粗略的初始优化来实现这一点。具体来说，我们使用可用的 SfM 点启动整个场景的默认3DGS优化，并添加一个辅助的天空盒。这个粗略模型作为提供背景细节的最小基础，即场景中给定部分之外的部分。在极大场景的情况下，如果存储SfM点会超出RAM容量，粗略优化本身可以分成多个步骤进行，部分中间结果会被流式传输到磁盘。我们将场景划分为足够大的块，以便为常见的现实世界元素（包括汽车、建筑物和纪念碑）建立足够的上下文。对于每个块，我们选择所有在块范围内或在块范围的2倍以内且在块范围内有超过50个SfM点的摄像机。</p>
<h3 id="52-块尺度的训练">5.2. 块尺度的训练<a hidden class="anchor" aria-hidden="true" href="#52-块尺度的训练">#</a></h3>
<p>我们对每个块独立进行训练；然后将结果用于为每个块创建层次结构，随后进行优化和整合步骤。在大型数据集中，典型的块与原始3DGS设置中使用的数据有显著不同。特别是，场景的范围显著大于Mip-NeRF 360等数据集的小场景。此外，捕获密度也要低得多，而且不是“以物体为中心”的。这使得优化更加困难，因为光线空间没有均匀覆盖。数据还包含曝光变化、人类和需要在优化中去除和忽略的移动物体（如汽车、自行车等）。</p>
<p>我们定义了一个围绕场景范围的天空盒，即在直径为场景十倍的球体上放置100,000个3DGS基元以捕获天空的效果。我们加载场景的粗略优化结果，这将用于块之外的所有内容；这也防止了每个块在天空上生成不一致的内容。我们使用3DGS优化方法和正确的抗锯齿技术来训练块内的内容。我们对块外的粗略环境和天空盒进行小范围的临时优化，特别是仅优化不透明度和SH系数。</p>
<p>原始的3DGS优化通过收集统计数据来决定是否在固定间隔内对高斯进行稠密化。具体来说，稠密化策略基于固定次数迭代中屏幕空间位置梯度的平均值。然而，在无界场景中存在两个主要问题。首先，这一策略很少阻止高斯稠密化，无论它们是否足够精细以建模局部细节。其次，具有稀疏、分散摄像机的数据集（例如城市穿越捕捉的情况）总体上稠密化的倾向更低。我们通过将稠密化策略改为考虑观察到的屏幕空间梯度的最大值而不是其平均值来解决这两个问题，这在稀疏捕捉的情况下不再可靠。我们拥有的稀疏摄像机捕捉不足以提供高质量的重建信息，例如在城市驾驶场景中的街道。我们进行单目深度预测，基于SfM点缩放和移动深度，并使用它来正则化优化。这改善了视觉质量，特别是对于道路。</p>
<h3 id="53-块整合和渲染">5.3. 块整合和渲染<a hidden class="anchor" aria-hidden="true" href="#53-块整合和渲染">#</a></h3>
<p>每个块从COLMAP的每块细化处理中获取SfM点，以及其相邻块中基本框架中包含的3D高斯。与一个块及其层次结构相关的3D高斯因此有时会位于块本身之外。在整合阶段，如果与块 $i$ 相关但位于块外的原语更接近另一个块$j\neq i$，则将其删除。整合还会创建一个具有整个场景根节点的全局层次结构。渲染是通过设置粒度阈值并找到相应的剪切点来执行的。我们每2帧更新一次剪切点，通过从CPU RAM传输节点到GPU来添加细节，并每100帧进行一次清理。</p>
<h2 id="6-附录">6. 附录<a hidden class="anchor" aria-hidden="true" href="#6-附录">#</a></h2>
<h3 id="61-如何降低高斯混合模型的复杂度">6.1. 如何降低高斯混合模型的复杂度<a hidden class="anchor" aria-hidden="true" href="#61-如何降低高斯混合模型的复杂度">#</a></h3>
<p>假设我们有一个分布，其由 $k$ 个 $d$ 纬高斯函数的高斯混合模型构成，可以写作：
</p>
$$
f(y)=\sum_{i=1}^k\alpha_iN(y;\mu_i,\Sigma_i)=\sum_{i=1}^k\alpha_if_i(y)
$$<p>
我们希望找到另一个高斯混合模型 $g(y)$，有：
</p>
$$
g(y) = \sum_{i=1}^{m}\beta_ig_i(y)
$$<p>
其中$m<k$。即我们希望通过一个较小的高斯混合模型描述较大高斯混合模型所蕴含的信息。那么不妨用用 KL 散度来描述用 $g(y)$ 代替 $f(y)$ 时的性能损失，即：
</p>
$$
\hat g = \arg\min_g KL(f\mid\mid g)=\arg\min_g\int f \log g
$$<p>
但是上式高度非线性且很难优化，我们很难解析的写出其形式。但是我们可以将两个模型 $f,g$ 之间的距离用如下形式定义为：
</p>
$$
d(f,g)=\sum_{i=1}^k\alpha_i\min_{j=1}^mKL(f_i||g_j)
$$<p>
可以直观地认为，如果 $f$ 的分量 $i$ 生成的所有点都必须在 $g$ 的单个分量下编码，则 $f$ 在模型 $g$ 下生成数据的编码成本。这个模型将原本复杂的高斯混合模型之间的 KL 散度变为高斯分布之间的 KL 散度。对于高斯分布 $\mathcal N(\mu_1, \Sigma_1), \mathcal N(\mu_2, \Sigma_2)$，其 KL 散度可以给出：
</p>
$$
\frac12(\log\frac{|\Sigma_2|}{|\Sigma_1|}+Tr(\Sigma_2^{-1}\Sigma_1)+(\mu_1-\mu_2)^T\Sigma_2^{-1}(\mu_1-\mu_2)-d).
$$<p>
此时，我们定义：
</p>
$$
\hat g = \arg\min_gd(f,g)
$$<p>
幸运的是，当 $k=1$，即将 $f$ 合并为一个高斯函数时，有上式有解析解。我们不加证明的给出：
</p>
$$
\mu_{j}^{\prime}=\frac{1}{\beta_{j}}\sum_{i=0}^m\alpha_{i}\mu_{i},\quad\Sigma_{j}^{\prime}=\frac{1}{\beta_{j}}\sum_{i=0}^m\alpha_{i}\left(\Sigma_{i}+(\mu_{i}-\mu_{j}^{\prime})(\mu_{i}-\mu_{j}^{\prime})^{T}\right)
$$<p>
其中：
</p>
$$
\beta_j = \sum_{i=1}^m \alpha_i
$$<h2 id="参考">参考<a hidden class="anchor" aria-hidden="true" href="#参考">#</a></h2>
<p><a href="https://arxiv.org/abs/2406.12080">A Hierarchical 3D Gaussian Representation for Real-Time Rendering of Very Large Datasets</a></p>
<p><a href="https://proceedings.neurips.cc/paper/2004/file/36e729ec173b94133d8fa552e4029f8b-Paper.pdf">Hierarchical Clustering of a Mixture Model</a></p>
<p><a href="https://arxiv.org/abs/physics/0004057">The information bottleneck method</a></p>


  </div>

  <footer class="post-footer">
    <ul class="post-tags">
      <li><a href="https://wangjv0812.github.io/WangJV-Blog-Pages/tags/3d-splatting/">3D Splatting</a></li>
      <li><a href="https://wangjv0812.github.io/WangJV-Blog-Pages/tags/gaussian-splatting/">Gaussian Splatting</a></li>
      <li><a href="https://wangjv0812.github.io/WangJV-Blog-Pages/tags/hierarchical-rendering/">Hierarchical Rendering</a></li>
      <li><a href="https://wangjv0812.github.io/WangJV-Blog-Pages/tags/%E4%BD%93%E6%B8%B2%E6%9F%93/">体渲染</a></li>
      <li><a href="https://wangjv0812.github.io/WangJV-Blog-Pages/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9B%BE%E5%BD%A2%E5%AD%A6/">计算机图形学</a></li>
    </ul>
<nav class="paginav">
  <a class="prev" href="https://wangjv0812.github.io/WangJV-Blog-Pages/2024/10/barf-bundle-adjusting-neural-radiance-field/">
    <span class="title">« Prev</span>
    <br>
    <span>BARF: Bundle Adjusting Neural Radiance Field</span>
  </a>
  <a class="next" href="https://wangjv0812.github.io/WangJV-Blog-Pages/2024/05/mathematics-in-3dgs-2/">
    <span class="title">Next »</span>
    <br>
    <span>Mathematics In 3DGS 2</span>
  </a>
</nav>

  </footer>
</article>
    </main>
    
<footer class="footer">
        <span>&copy; 2025 <a href="https://wangjv0812.github.io/WangJV-Blog-Pages/">WangJV Blog</a></span> · 

    <span>
        Powered by
        <a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
        <a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
    </span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
        <path d="M12 6H0l6-6z" />
    </svg>
</a>

<script>
    let menu = document.getElementById('menu')
    if (menu) {
        menu.scrollLeft = localStorage.getItem("menu-scroll-position");
        menu.onscroll = function () {
            localStorage.setItem("menu-scroll-position", menu.scrollLeft);
        }
    }

    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener("click", function (e) {
            e.preventDefault();
            var id = this.getAttribute("href").substr(1);
            if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
                document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
                    behavior: "smooth"
                });
            } else {
                document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
            }
            if (id === "top") {
                history.replaceState(null, null, " ");
            } else {
                history.pushState(null, null, `#${id}`);
            }
        });
    });

</script>
<script>
    var mybutton = document.getElementById("top-link");
    window.onscroll = function () {
        if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
            mybutton.style.visibility = "visible";
            mybutton.style.opacity = "1";
        } else {
            mybutton.style.visibility = "hidden";
            mybutton.style.opacity = "0";
        }
    };

</script>
<script>
    document.getElementById("theme-toggle").addEventListener("click", () => {
        if (document.body.className.includes("dark")) {
            document.body.classList.remove('dark');
            localStorage.setItem("pref-theme", 'light');
        } else {
            document.body.classList.add('dark');
            localStorage.setItem("pref-theme", 'dark');
        }
    })

</script>
<script>
    document.querySelectorAll('pre > code').forEach((codeblock) => {
        const container = codeblock.parentNode.parentNode;

        const copybutton = document.createElement('button');
        copybutton.classList.add('copy-code');
        copybutton.innerHTML = 'copy';

        function copyingDone() {
            copybutton.innerHTML = 'copied!';
            setTimeout(() => {
                copybutton.innerHTML = 'copy';
            }, 2000);
        }

        copybutton.addEventListener('click', (cb) => {
            if ('clipboard' in navigator) {
                navigator.clipboard.writeText(codeblock.textContent);
                copyingDone();
                return;
            }

            const range = document.createRange();
            range.selectNodeContents(codeblock);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            try {
                document.execCommand('copy');
                copyingDone();
            } catch (e) { };
            selection.removeRange(range);
        });

        if (container.classList.contains("highlight")) {
            container.appendChild(copybutton);
        } else if (container.parentNode.firstChild == container) {
            
        } else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
            
            codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
        } else {
            
            codeblock.parentNode.appendChild(copybutton);
        }
    });
</script>
</body>

</html>
